package co.baiku.boot.aliyun;

import co.baiku.boot.common.message.Message;
import co.baiku.boot.common.tools.JsonTools;
import co.baiku.boot.common.tools.StringTools;
import co.baiku.boot.config.AliyunSmsConfig;
import co.baiku.boot.config.AliyunSmsTemplate;
import com.aliyuncs.AcsRequest;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 阿里云短信发送插件
 */
@SuppressWarnings("ALL")
@Component
@ConditionalOnProperty("ajavaer.aliyun.sms.access-key-id")
public class AliyunSms implements InitializingBean {
    private Logger log = LoggerFactory.getLogger(AliyunSms.class);

    @Resource
    private AliyunSmsConfig smsConfig;
    @Resource
    private Environment environment;
    private IAcsClient iAcsClient = null;
    private Boolean isDebug = true;

    public AliyunSms() {
    }

    public AliyunSms(AliyunSmsConfig smsConfig) {
        this.smsConfig = smsConfig;
        this.afterPropertiesSet();
    }

    @Override
    public void afterPropertiesSet() {
        iAcsClient = createClient();
        this.isDebug = this.environment.getProperty("ajavaer.debug", Boolean.class, true);
        if (isDebug) {
            log.debug("Aliyun Sms init");
        }
    }

    private IAcsClient createClient() {
        DefaultProfile.addEndpoint(smsConfig.getRegionId(), smsConfig.getProduct(), smsConfig.getEndpoint());
        return new DefaultAcsClient(DefaultProfile.getProfile(smsConfig.getProfile(), smsConfig.getAccessKeyId(), smsConfig.getAccessKeySecret()));
    }

    /**
     * 指定模版发送
     *
     * @param phone
     * @param param
     * @param templateName
     * @return
     */
    public Message send(String phone, String param, String templateName) {
        AliyunSmsTemplate template = smsConfig.getByName(templateName);
        if (template != null) {
            return send(phone, param, template.getSignName(), template.getTemplateCode(), template.getEnable());
        }
        return Message.fail(StringTools.format("短信模版[{}]不存在", templateName));
    }

    public Message send(String phone, String param, String signName, String templateCode, Boolean enable) {
        if (StringTools.isBlank(phone)) {
            return Message.fail(HttpStatus.BAD_REQUEST, "手机号不能为空");
        }
        SendSmsRequest request = new SendSmsRequest();
        request.setSignName(signName);
        request.setTemplateCode(templateCode);
        phone = phone.replaceAll("-| |\\+", "");
        if (phone.startsWith("86")) {
            phone = phone.substring(2);
        }
        request.setMethod(MethodType.POST);
        request.setPhoneNumbers(phone);
        //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
        request.setTemplateParam(param);
        try {
            SendSmsResponse smsResponse = sendSms(request, enable);
            //请求成功
            if (smsResponse.getCode() != null && smsResponse.getCode().equals("OK")) {
                if (isDebug) {
                    log.debug("Sms发送成功:" + JsonTools.beanToJson(request));
                }
                return Message.success("发送成功");
            } else {
                log.error("发送短信失败:" + smsResponse.getCode() + " " + smsResponse.getMessage());
                return Message.fail(HttpStatus.BAD_REQUEST, smsResponse.getMessage());
            }
        } catch (ClientException e) {
            log.error("发送短信失败:" + e.getMessage(), e);
            return Message.fail(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    /**
     * 发送短信
     *
     * @param phone  手机号
     * @param param  参数
     *               <p>友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败</p>
     *               <p>示例:<br/>
     *               request.setTemplateParam("{\"name\":\"Tom\", \"code\":\"123\"}");
     *               </p>
     * @param enable 是否真实发送
     * @return
     */
    public Message send(String phone, String param, Boolean enable) {
        return send(phone, param, smsConfig.getSignName(), smsConfig.getTemplateCode(), enable);
    }


    public SendSmsResponse sendSms(SendSmsRequest request, boolean enable) throws ClientException {
        SendSmsResponse response;
        if (enable) {
            response = iAcsClient.getAcsResponse(request);
            log.info(StringTools.format("短信发送,request:{0}", JsonTools.beanToJson(request)));
            return response;
        } else {
            response = new SendSmsResponse();
            response.setCode("OK");
            response.setMessage("发送成功");
        }
        return response;
    }

    /**
     * 查询短信发送详情
     *
     * @param request
     * @return
     */
    public Message<QuerySendDetailsResponse> querySendDetails(QuerySendDetailsRequest request) {
        if (request == null || StringTools.isBlank(request.getPhoneNumber())) {
            return Message.fail(HttpStatus.BAD_REQUEST, "手机号不能为空");
        }
        QuerySendDetailsResponse detailResponse = null;
        try {
            detailResponse = (QuerySendDetailsResponse) sendRequest(request, true);
            String code = detailResponse.getCode();
            if (code.equalsIgnoreCase("OK")) {
                return Message.result(detailResponse);
            }
            return Message.fail("", detailResponse);
        } catch (ClientException e) {
            log.error("发送短信失败:" + e.getMessage(), e);
            return Message.fail(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }


    public AcsResponse sendRequest(AcsRequest request, boolean enable) throws ClientException {
        AcsResponse response = null;
        if (enable) {
            response = iAcsClient.getAcsResponse(request);
            log.info(StringTools.format("短信发送,request:{0}", JsonTools.beanToJson(request)));
            return response;
        } else {
            response = new SendSmsResponse();
            ((SendSmsResponse) response).setCode("OK");
            ((SendSmsResponse) response).setMessage("发送成功");
        }
        return response;
    }

    public AliyunSmsConfig getSmsConfig() {
        return smsConfig;
    }
}
